#include <iostream>
#include <cstdlib>
#include <ctime>
#include <sstream>

#include "traffic_sim.H"

using namespace Traffic_Sim;

Traffic_Graph * graph;

const string nodos[] = {"Las Tapias", "Humboldt", "Pie del Llano", "Casa Blanca", "Alto Prado", "Mercado", "Medicina", "Santa Juana", "Glorias Patrias", "Santo Niño", "Viaducto", "Santa Barbara", "Mc Donalds" };

void create_street(string src_node_desc, string dest_node_desc, int delay, int capacity, string street_name) 
{
  Traffic_Node_Info info1(src_node_desc);
  Traffic_Graph::Node * n1 = graph->search_node(info1);
  if (n1 == NULL) 
  {
    n1 = graph->insert_node(info1);
  }

  Traffic_Node_Info info2(dest_node_desc);
  Traffic_Graph::Node * n2 = graph->search_node(info2);
  if (n2 == NULL)
  {
    n2 = graph->insert_node(info2);
  }
  Traffic_Arc_Info info_arc(street_name, delay, capacity);
  cout << "Creada calle " << info_arc.description << " desde " << info1.description  << " hasta " << info2.description << endl;
  graph->insert_arc(n1, n2, info_arc);
}

void create_semaphore_agent(int id, string node_desc, int arc_count,  
    long activation_time, string* arc_nodes_desc )
{
  stringstream agent_name_strm(stringstream::out) ;
  agent_name_strm << "Tricolor en " << node_desc;

  Traffic_Node_Info node_info(node_desc);
  Traffic_Node * node = graph->search_node(node_info);

  Traffic_Semaphore * semaphore;

  string agent_name = agent_name_strm.str();

  if (arc_count == 3)
  {
    semaphore = new Three_Way_Traffic_Semaphore(id, agent_name, node, arc_count);
  } 
  else 
  {
    semaphore = new Traffic_Semaphore(id, agent_name, node,  arc_count);
  }

  for (int i = 0; i < arc_count; i++)
  {
    Traffic_Node_Info dest_node_info(arc_nodes_desc[i]);
    Traffic_Node * dest_node = graph->search_node(dest_node_info);

    Traffic_Arc * arc = graph->search_arc(node, dest_node);
    semaphore->set_arc_index(arc, i);
  }

  Traffic_Agent_Impl::create_agent_in_node(semaphore, graph, node, activation_time);
  cout << "Creado tricolor en " << node_desc << endl;
}

void configure_traffic_graph()
{
  // Crear grafo
  string* arcs_desc;
  create_street("Las Tapias", "Humboldt", 5, 20, "Albarregas");
  create_street("Las Tapias", "Pie del Llano", 10, 20, "Av. Andres Bello");
  create_street("Humboldt", "Santo Niño", 6, 20, "Av. Humboldt");
  create_street("Humboldt", "Santa Barbara", 11, 20, "Las Americas 1");
  create_street("Santo Niño", "Casa Blanca", 20, 20, "Panamericana");
  create_street("Santa Barbara", "Mc Donalds", 8, 20, "Las Americas 2");
  create_street("Pie del Llano", "Santa Barbara", 7, 20, "Sucre");
  //string *   

  //create_semaphore_agent (1, "Santa Barbara", 3, 1, );
  create_street("Pie del Llano", "Santa Juana", 5, 20, "Av. Ppal Santa Juana");
  create_street("Santa Juana", "Medicina", 16, 20, "16 de Septiembre");
  create_street("Medicina", "Glorias Patrias", 4, 20, "Don Tulio");
  create_street("Pie del Llano", "Glorias Patrias", 15, 20, "Av. Urdaneta");
  create_street("Glorias Patrias", "Mercado", 6, 20, "Miranda");
  create_street("Mc Donalds", "Mercado", 7, 20, "Las Americas 3");
  create_street("Mc Donalds", "Casa Blanca", 3, 20, "El Rodeo");
  //create_semaphore_agent
  create_street("Casa Blanca", "Alto Prado", 14, 20, "Los Proceres");
  create_street("Mercado", "Viaducto", 7, 20, "Las Americas 4");
  create_street("Viaducto", "Alto Prado", 6, 20, "Campo Elias");
  
}

Traffic_Agent * get_semaphore_agent(string node_desc)
{
  Traffic_Node_Info node_info(node_desc);
  Traffic_Node * node = graph->search_node(node_info);
  return graph->search_agent(node->get_info().semaphore);
}

void create_agents_in_graph()
{
  cout<<"Creando los agentes en el Grafo"<<endl;
  for (int i = 1; i <= 5; i++) 
  {
 		stringstream agent_name_strm(stringstream::out) ;
    agent_name_strm << "Agente " << i;
    string agent_name =  agent_name_strm.str();
    Traffic_Random_Vehicle *vehicle = new Traffic_Random_Vehicle(i, agent_name);
    int index = rand() % 13;

    Traffic_Graph::Node * n1 = graph->search_node(Traffic_Node_Info(nodos[index]));
    Traffic_Agent_Impl::create_agent_in_node(vehicle, graph, n1, 10 + index);
  }
}

int main()
{
	srand((unsigned)time(0));
  graph = new Traffic_Graph(1);
  configure_traffic_graph();
  create_agents_in_graph();
 
  // Comenzar la ejecución
  //graph->start_graph();
  graph->run_static();
  
  // Permitir que se ejecute por 10 segundos
  //sleep(10);
  //graph->stop_graph(); 
  
  delete graph;

}
